package com.yzh.wanandroid.repository

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.withContext
import java.io.IOException

class BaseRepository<T> constructor(
    private var owner: LifecycleOwner?,
    callBack: BaseRepository<T>.() -> Unit
) {

    private var onLoading: (() -> Unit)? = null

    private var onSuccess: ((data: T) -> Unit)? = null

    private var onError: ((code: Int, message: String) -> Unit)? = null

    init {
        callBack()
    }

    fun loading(onLoading: (() -> Unit)): BaseRepository<T> {
        this.onLoading = onLoading
        return this
    }

    fun loadData(block: suspend () -> T): BaseRepository<T> {
        var response: T?
        var netJob: Job? = null
        owner?.run {
            netJob = lifecycleScope.launchWhenStarted {
                withContext(Dispatchers.Main) {
                    onLoading?.invoke()
                }
                response = withContext(Dispatchers.IO) {
                    try {
                        block.invoke()
                    } catch (e: IOException) {
                        e.printStackTrace()
                        withContext(Dispatchers.Main) {
                            onError?.invoke(404, "网络异常")
                        }
                        null
                    }
                }
                withContext(Dispatchers.Main) {
                    if (response != null) {
                        response?.let {
                            onSuccess?.invoke(it)
                        }
                    } else {
                        netJob?.cancel()
                    }
                }
            }
        }
        return this
    }

    fun success(onSuccess: ((data: T) -> Unit)): BaseRepository<T> {
        this.onSuccess = onSuccess
        return this
    }

    fun error(onError: ((code: Int, message: String) -> Unit)): BaseRepository<T> {
        this.onError = onError
        return this
    }
}